TypeScript の const Type Parameters ってなんだよ
AI が書いてきたコードが理解できなかったので勉強する
code:ts
type HasNames = { names: readonly string[] };
function getNamesExactly<T extends HasNames>(arg: T): T"names" { return arg.names;
}
// Inferred type: string[]
⬆️でもいい感じに推論してくれて string[] を得ているけど、ちょっと曖昧
本当は readonly ["Alice", "Bob", "Eve"] が欲しい
そこで⬇️のコード、as const を引数のオブジェクトにつければいい
code:ts
だけどこの書き方は面倒だし忘れちゃう
This can be cumbersome and easy to forget.
code:ts
type HasNames = { names: readonly string[] };
function getNamesExactly<const T extends HasNames>(arg: T): T"names" { return arg.names;
}
// NOTE: Didn't need to write as const here
ただし、const 修飾子は mutable な値を拒否しないし、immutable な型制約も要求しないことに注意が必要
mutable な配列型を型制約に用いるとせっかくの const 推論が潰れてしまうことになる
code:ts
declare function fnBad<const T extends string[]>(arg: T): void;
// 'T' is still 'string[]' since 'readonly "a", "b", "c"' is not assignable to 'string[]' declare function fnGood<const T extends readonly string[]>(arg: T): void;
(const type parameter なのでリテラルまたはタプルで取りたがる) しかし型制約が string[] と mutable
readonly ["a", "b", "c"] は string[] に代入できない
推論に失敗
推論は型制約側にフォールバックして T = string[] になる